package com.demo.jvm.structure;

import java.util.ArrayList;
import java.util.List;

/**
 * 类的访问标识
 * <p>
 * Flag Name	Value	Interpretation
 * ACC_PUBLIC	0x0001	Declared public; may be accessed from outside its package.
 * ACC_FINAL	0x0010	Declared final; no subclasses allowed.
 * ACC_SUPER	0x0020	Treat superclass methods specially when invoked by the invokespecial instruction.
 * ACC_INTERFACE	0x0200	Is an interface, not a class.
 * ACC_ABSTRACT	0x0400	Declared abstract; must not be instantiated.
 * ACC_SYNTHETIC	0x1000	Declared synthetic; not present in the source code.
 * ACC_ANNOTATION	0x2000	Declared as an annotation type.
 * ACC_ENUM	0x4000	Declared as an enum type.
 */
public enum ClassAccessFlagsType {
    PUBLIC("ACC_PUBLIC", 0x0001, "public", 1),
    FINAL("ACC_FINAL", 0x0010, "final", 16),
    SUPER("ACC_SUPER", 0x0020, "super", 32),
    INTERFACE("ACC_INTERFACE", 0x0200, "interface", 512),
    ABSTRACT("ACC_ABSTRACT", 0x0400, "abstract", 1024),
    SYNTHETIC("ACC_SYNTHETIC", 0x1000, "synthetic", 4096),
    ANNOTATION("ACC_ANNOTATION", 0x2000, "annotation", 8192),
    ENUM("ACC_ENUM", 0x4000, "enum", 16384),
    ;

    private String name;
    private int valueOf16;
    private String description;
    private int valueOf10;

    ClassAccessFlagsType(String name, int valueOf16, String description, int valueOf10) {
        this.name = name;
        this.valueOf16 = valueOf16;
        this.description = description;
        this.valueOf10 = valueOf10;
    }

    public static List<ClassAccessFlagsType> getaccessFlagsTypeByValue(int value) {
        List<ClassAccessFlagsType> types = new ArrayList<>();
        while (value > 0) {
            if (value >= ENUM.valueOf10) {
                types.add(ENUM);
                value = value - ENUM.valueOf10;
            } else if (value >= ANNOTATION.valueOf10) {
                types.add(ANNOTATION);
                value = value - ANNOTATION.valueOf10;
            } else if (value >= SYNTHETIC.valueOf10) {
                types.add(SYNTHETIC);
                value = value - SYNTHETIC.valueOf10;
            } else if (value >= ABSTRACT.valueOf10) {
                types.add(ABSTRACT);
                value = value - ABSTRACT.valueOf10;
            } else if (value >= INTERFACE.valueOf10) {
                types.add(INTERFACE);
                value = value - INTERFACE.valueOf10;
            } else if (value >= SUPER.valueOf10) {
                types.add(SUPER);
                value = value - SUPER.valueOf10;
            } else if (value >= FINAL.valueOf10) {
                types.add(FINAL);
                value = value - FINAL.valueOf10;
            } else if (value >= PUBLIC.valueOf10) {
                types.add(PUBLIC);
                value = value - PUBLIC.valueOf10;
            }
        }
        return types;
    }
}
